package com.hk.juc.util;

import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.*;

/**
 * CyclicBarrier和CountDownLatch的区别：
 *      CountDownLatch的计数器只能使用一次，而CyclicBarrier的计数器可以使用reset()方法重
 *  置。所以CyclicBarrier能处理更为复杂的业务场景。例如，如果计算发生错误，可以重置计数
 *  器，并让线程重新执行一次。
 *
 */
@Slf4j
public class CyclicBarrierBankWaterService implements Runnable {

    //4个内存屏障,this指的是当前对象：CyclicBarrierBankWaterService
    public CyclicBarrier cyclicBarrier = new CyclicBarrier(4, this);

    //4个线程
    private Executor executor = Executors.newFixedThreadPool(4);

    //用来存在计算的数据
    private ConcurrentHashMap<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();

    private void count() {
        for (int i = 0; i < 4; i++) {
            int tempValue = i;
            executor.execute(() -> {
                concurrentHashMap.put(Thread.currentThread().getName(), tempValue);
                try {
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }


    @Override
    public void run() {
        int reuslt = 0;
        for (Map.Entry<String, Integer> sheet : concurrentHashMap.entrySet()) {
            reuslt += sheet.getValue();
        }
        concurrentHashMap.put("total", reuslt);
        log.info("total: {}", reuslt);
    }


    public static void main(String[] args) {
        /**
         * 使用线程池创建4个线程，分别计算每个sheet里的数据，每个sheet计算结果是1，再由
         * BankWaterService线程汇总4个sheet计算出的结果，输出结果如下:
         *  00:32:45.748 [pool-1-thread-2] INFO com.hk.juc.util.CyclicBarrierBankWaterService - total: 6
         */
        CyclicBarrierBankWaterService service = new CyclicBarrierBankWaterService();
        service.count();

    }
}
